Skip to content

Add opt-in telemetry auto-configuration#553

Open
rbarbadillo wants to merge 3 commits into
mainfrom
rbarbadillo/telemetry-auto-config
Open

Add opt-in telemetry auto-configuration#553
rbarbadillo wants to merge 3 commits into
mainfrom
rbarbadillo/telemetry-auto-config

Conversation

@rbarbadillo
Copy link
Copy Markdown
Contributor

@rbarbadillo rbarbadillo commented May 22, 2026

Summary

Adds opt-in OpenTelemetry telemetry auto-configuration for the Python SDK.

The SDK already emits spans via the OTel API. This PR adds a mistralai[telemetry] optional extra with the OTel SDK/exporter dependencies, plus helper/env-based configuration so users do not need to manually wire an OTLP exporter, endpoint, auth headers, span processor, and tracer provider just to get Mistral SDK traces working.

Telemetry remains off by default.

Usage

Explicit opt-in with an SDK-owned telemetry provider:

from mistralai import Mistral
from mistralai.extra.observability import configure_telemetry

client = Mistral(api_key="...")
configure_telemetry(client)

client.chat.complete(...)

Use the global OpenTelemetry provider:

from mistralai import Mistral
from mistralai.extra.observability import configure_telemetry

client = Mistral(api_key="...")
configure_telemetry(client, provider="global")

client.chat.complete(...)

Attach an already constructed provider:

from opentelemetry.sdk.trace import TracerProvider
from mistralai import Mistral
from mistralai.extra.observability import configure_telemetry

client = Mistral(api_key="...")
configure_telemetry(client, provider=TracerProvider())

client.chat.complete(...)

Or configure by environment:

MISTRAL_SDK_TELEMETRY=dedicated
MISTRAL_SDK_TELEMETRY=global
MISTRAL_SDK_TELEMETRY=false

Longer term, the target generated API is:

client = Mistral(api_key="...", telemetry=True)

That constructor parameter is not included here because the constructor is Speakeasy-generated; this PR keeps the implementation in hand-owned code and leaves the path open for codegen support later.

Behavior

  • Adds mistralai[telemetry] with:
    • opentelemetry-sdk
    • opentelemetry-exporter-otlp-proto-http
  • Keeps telemetry disabled by default.
  • Enables SDK-owned telemetry with MISTRAL_SDK_TELEMETRY=dedicated or configure_telemetry(client).
  • Uses the global OpenTelemetry provider with MISTRAL_SDK_TELEMETRY=global or configure_telemetry(client, provider="global").
  • Attaches caller-owned providers with configure_telemetry(client, provider=<TracerProvider>).
  • Keeps set_tracer_provider(client, provider) as a compatibility wrapper over configure_telemetry(client, provider=provider).
  • Treats MISTRAL_SDK_TELEMETRY=false as an env opt-out.
  • Keeps internal telemetry=False handling for future SDK config/env resolution, but does not expose that on the public helper API.
  • Env-based dedicated auto-config skips if the application already has a real global OTel provider and logs a debug message.
  • Explicit configure_telemetry(client) can still attach an SDK-owned per-client provider even when a global provider exists.
  • Respects OTEL_EXPORTER_OTLP_ENDPOINT / OTEL_EXPORTER_OTLP_TRACES_ENDPOINT as exporter destination config only when telemetry is explicitly enabled.
  • Raises a clear error pointing to mistralai[telemetry] if optional telemetry dependencies are missing.

@rbarbadillo rbarbadillo requested review from Yousria and jsurloppe May 22, 2026 19:02
@rbarbadillo rbarbadillo self-assigned this May 22, 2026
Comment thread uv.lock

def configure_telemetry(
client: "Mistral",
telemetry: bool | None = None,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the telemetry bool on configure_telemetry makes the public API a bit harder to reason about. Since calling configure_telemetry(...) is already explicit, configure_telemetry(client, telemetry=True) feels redundant, while configure_telemetry(client) being a no-op unless env is set is surprising.

Could we make this provider-oriented instead? For example:

  • provider="dedicated" creates the SDK-owned internal provider/exporter.
  • provider="global" just use the default provider.
  • provider=<TracerProvider> attaches a caller-provided provider.

Copy link
Copy Markdown
Contributor Author

@rbarbadillo rbarbadillo May 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I agree that configure_telemetry(client, telemetry=True) is redundant, and configure_telemetry(client) being env-dependent is surprising.

I've gone for this: 42ab887

I think the provider-oriented shape overlaps a little with existing behavior:

  • provider="global" is already the default OpenTelemetry path when no per-client provider is attached (so you don't need to call configure_telemetry at all)
  • provider=<TracerProvider> is already covered by set_tracer_provider(client, provider).
  • the only missing public action is “create the SDK-owned telemetry provider/exporter,” which is what configure_telemetry(client) will now do.

The False case still exists internally for env/future SDK config resolution, but it isn’t exposed on the public helper anymore.

Wdyt?

Copy link
Copy Markdown

@jsurloppe jsurloppe May 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

provider="global" is already the default OpenTelemetry path when no per-client provider is attached (so you don't need to call configure_telemetry at all)
You mean only if you set the env var, right?
What if I'm in an env where I don't easily control the environment? (workflow maybe?)

Intuitively, I think if we need this new configure_telemetry function, we shouldn't need to keep set_tracer_provider.

From the user POV, you get now 3 distinct path to configure a minor diff.

My opinion is, if we need this new configure_telemetry function, then it should cover all cases and replace previous configuration method.

also, about our env var, we should make it like:
MISTRAL_SDK_TELEMETRY=<global|dedicated>
(or accept True as "global", if we need to keep compatibility)

and detecting this env var should call configure_telemetry with it value.

like this we only maintain one code path and the decision tree in configure_telemetry should be simpler.

and the developer only need to call that function if:

  • he can't (or prefer not) to rely on the environment.
  • he want to set an already constructed provider.

Copy link
Copy Markdown
Contributor Author

@rbarbadillo rbarbadillo May 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the push-back! I agree, updated in d7be63b.

The public helper now covers:

  • configure_telemetry(client) / provider="dedicated" creates the SDK-owned telemetry provider/exporter.
  • configure_telemetry(client, provider="global") uses the global OpenTelemetry provider path, without requiring env var control.
  • configure_telemetry(client, provider=<TracerProvider>) attaches an already constructed provider.

The env var now mirrors that shape explicitly:

MISTRAL_SDK_TELEMETRY=dedicated
MISTRAL_SDK_TELEMETRY=global
MISTRAL_SDK_TELEMETRY=false

@rbarbadillo rbarbadillo force-pushed the rbarbadillo/telemetry-auto-config branch from aa7ab84 to bf80c79 Compare May 25, 2026 11:03
@rbarbadillo rbarbadillo marked this pull request as ready for review May 25, 2026 11:12
@rbarbadillo rbarbadillo requested a review from jsurloppe May 25, 2026 11:12
@rbarbadillo rbarbadillo force-pushed the rbarbadillo/telemetry-auto-config branch 4 times, most recently from ab1403d to a55a112 Compare May 25, 2026 21:50
@rbarbadillo rbarbadillo force-pushed the rbarbadillo/telemetry-auto-config branch from a55a112 to d7be63b Compare May 25, 2026 22:16
@rbarbadillo rbarbadillo requested review from Nelson-PROIA and removed request for Yousria May 25, 2026 22:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants